package com.plian.system.service.sys.warning.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.sys.WarningMessageConstant;
import com.plian.system.dao.sys.user.UserDao;
import com.plian.system.entity.sys.Message;
import com.plian.system.entity.sys.Org;
import com.plian.system.entity.sys.User;
import com.plian.system.entity.sys.warning.WarningMessage;
import com.plian.system.mapper.sys.SysUserMapper;
import com.plian.system.mapper.sys.warning.WarningMessageMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.message.IMessageService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.sys.warning.IWarningMessageConfigService;
import com.plian.system.service.sys.warning.IWarningMessageService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.sys.UserOrgVO;
import com.plian.system.vo.sys.warning.WarningMessageVO;
import com.plian.system.wrapper.sys.warning.WarningMessageWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

@Service
@AllArgsConstructor
@Slf4j
public class WarningMessageServiceImpl extends BaseServiceImpl<WarningMessageMapper,WarningMessage> implements IWarningMessageService, BaseFlowService {

    private final FileService fileService;

    private final FormWorkflowService formWorkflowService;

    private final IFormCodeService formCodeService;

    private final WarningMessageWrapper warningMessageWrapper;

    private final IWarningMessageConfigService warningMessageConfigService;

    private final IOrgService orgService;

    private UserDao userDao;

    private IMessageService messageService;

    private SysUserMapper sysUserMapper;

    private final static String PROPERTY_FUND_NAME = "产权登记";

    @Override
    public boolean saveOrUpdate(WarningMessage warningMessage) {
        boolean flag = false;
        if (!Optional.ofNullable(warningMessage.getId()).isPresent()) {
            flag = true;
            warningMessage.setFormType(String.valueOf(FormTypeConstant.SYS_WARN_MESSAGE));
        }
        boolean result = super.saveOrUpdate(warningMessage);
        if (flag){
            fileService.saveAll(String.valueOf(warningMessage.getId()), warningMessage.getDocList());
        }else {
            fileService.edit(String.valueOf(warningMessage.getId()), warningMessage.getDocList());
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            WarningMessage warningMessage = getById(id);
            if (warningMessage == null) {
                return false;
            } else if (warningMessage.getStatus() != null &&
                    (warningMessage.getStatus() != FormStatusConstant.STASH && warningMessage.getStatus() != UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }
        return super.deleteLogic(ids);
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
    }

    @Override
    public Boolean reject(String id, int formState,String comment) {
        return handleStatus(Long.valueOf(id), formState);
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            WarningMessage warningMessage = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                warningMessage.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                warningMessage.setApprovedTime(now);
            }
            warningMessage.setStatus(updateStatus);
            updateById(warningMessage);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<WarningMessage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(WarningMessage::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<WarningMessage> warningMessages = list(queryWrapper);
        List<WarningMessageVO> warningMessageVOS = warningMessageWrapper.entityToVO(warningMessages);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(warningMessageVOS)){
                for (WarningMessageVO vo : warningMessageVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getWarningOrgName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getWarningOrg());
                    pd.put("formType", FormTypeConstant.SYS_WARN_MESSAGE);
                    pd.put("orgName", vo.getWarningOrgName());
                    pageDataList.add(pd);
                }
            }
            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.SYS_WARN_MESSAGE);
    }

    @Override
    public void sendMessages(Long id){
        WarningMessage warningMessage = getById(id);
        if (warningMessage == null){
            return;
        }

        //当前登陆用户
        String userId = TokenUtil.getTokenUserId();
        User tokenUser = sysUserMapper.selectById(userId);
        String name = tokenUser.getName();
        String warningOrg = warningMessage.getWarningOrg();
        Org org = orgService.getById(warningOrg);

        //获取要发送的人
        List<Message> messages = new ArrayList<>();
        if (WarningMessageConstant.IRS_GS_SOURCE == warningMessage.getWarningSource()){
            //工商  产权预警
            List<UserOrgVO> userOrgVOS = new ArrayList<>();
            List<UserOrgVO> tempOrgVOS = sysUserMapper.findUserOrgByFundNameAndOrgId(PROPERTY_FUND_NAME, warningMessage.getWarningOrg());
            if (CollectionUtil.isNotEmpty(tempOrgVOS)){
                userOrgVOS.addAll(tempOrgVOS);
            }
            if (orgService.checkIsGzw(TokenUtil.getTokenOrgId())){
                List<UserOrgVO> tempOrgVOS2 = sysUserMapper.findUserOrgByFundNameAndOrgId(PROPERTY_FUND_NAME, warningMessage.getSubordinateGroup());
                if (CollectionUtil.isNotEmpty(tempOrgVOS2)){
                    userOrgVOS.addAll(tempOrgVOS2);
                }
            }
            if (CollectionUtil.isNotEmpty(userOrgVOS)){
                for (UserOrgVO userOrgVO : userOrgVOS){
                    Message message = Message.builder().formId(id + "").orgName(userOrgVO.getOrgName())
                            .orgId(userOrgVO.getOrgId()).formType(String.valueOf(FormTypeConstant.SYS_WARN_MESSAGE)).formTypeName("智能预警").messageTime(DateUtil.now())
                            .createUser(userOrgVO.getUserId()).message("存在预警消息未反馈").sendUser(userId).sendUserName(name).isIgnore(0).build();
                    messages.add(message);
                }
            }
        }else {
            List<User> allUserById = warningMessageConfigService.getAllUserById(warningMessage.getWarningConfigId(), warningOrg);
            if (CollectionUtil.isNotEmpty(allUserById)){
                for (User user : allUserById){
                    Message message = Message.builder().formId(id + "").orgName(org.getName())
                            .orgId(warningOrg).formType(String.valueOf(FormTypeConstant.SYS_WARN_MESSAGE)).formTypeName("智能预警").messageTime(DateUtil.now())
                            .createUser(user.getId()).message("存在预警消息未反馈").sendUser(userId).sendUserName(name).isIgnore(0).build();
                    messages.add(message);
                }
            }
        }
        messageService.saveBatch(messages);
    }

    @Override
    public void propertyMessageChangeLight() {
        List<WarningMessage> messageList = list(Wrappers.<WarningMessage>lambdaQuery()
                .eq(WarningMessage::getWarningLightType, WarningMessageConstant.YELLOW_LIGHT)
                .ne(WarningMessage::getFeedbackStatus, WarningMessageConstant.FEED_BACK_STATUS)
                .eq(WarningMessage::getWarningSource, WarningMessageConstant.IRS_GS_SOURCE));
        if (CollectionUtil.isNotEmpty(messageList)){
            Date now = DateUtil.now();
            for (WarningMessage warningMessage : messageList){
                Date date = DateUtil.plusDays(warningMessage.getWarningDate(), 5);
                if (date.getTime() <= now.getTime()){
                    warningMessage.setWarningLightType(WarningMessageConstant.ORANGE_LIGHT);
                    saveOrUpdate(warningMessage);
                }
            }
        }
    }

    @Override
    public boolean feedback(WarningMessageVO warningMessageVO) {
        if (CollectionUtil.isEmpty(warningMessageVO.getIds())){
            return true;
        }
        return update(Wrappers.<WarningMessage>lambdaUpdate()
                .in(WarningMessage::getId, warningMessageVO.getIds())
                .set(WarningMessage::getFeedbackStatus, WarningMessageConstant.FEED_BACK_STATUS));
    }

    @Override
    public boolean feedbackReject(WarningMessageVO warningMessageVO) {
        if (CollectionUtil.isEmpty(warningMessageVO.getIds())){
            return true;
        }
        return update(Wrappers.<WarningMessage>lambdaUpdate()
                .eq(WarningMessage::getFeedbackStatus, WarningMessageConstant.FEED_BACK_STATUS)
                .in(WarningMessage::getId, warningMessageVO.getIds())
                .set(WarningMessage::getFeedbackStatus, WarningMessageConstant.REJECT_FEED_BACK_STATUS));
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(WarningMessage warningMessage) {
        boolean result = saveOrUpdate(warningMessage);
        return result;
    }

    @Override
    public ListResult<WarningMessageVO> list(Query query) {
        List<SearchEntity> entityList = query.getSearch();
        if (query.getAscs()==null&&query.getDescs()==null){
            query.setDescs("create_time");
        }
        QueryWrapper<WarningMessage> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new WarningMessage()), entityList
        );

        TokenSearch<WarningMessage> tokenSearch = new TokenSearch<>();
		tokenSearch.addTokenNoFlowQuery(queryWrapper, query);
        //todo 临时处理  后续加预警模块和用户关系表
        List<UserOrgVO> userOrgVOS = sysUserMapper.findUserOrgByFundName(PROPERTY_FUND_NAME, TokenUtil.getTokenUserId());
        List<UserOrgVO> gzwUserOrgVOS = sysUserMapper.findGzwUserOrgByFundName(PROPERTY_FUND_NAME, TokenUtil.getTokenUserId());
        if (CollectionUtil.isEmpty(userOrgVOS) && CollectionUtil.isEmpty(gzwUserOrgVOS)){
            queryWrapper.lambda().ne(WarningMessage::getWarningSource, WarningMessageConstant.IRS_GS_SOURCE);
        }

        IPage<WarningMessage> pages =page(Condition.getPage(query), queryWrapper);
        List<WarningMessageVO> warningMessageVOS = warningMessageWrapper.entityToVO(pages.getRecords());
        ListResult<WarningMessageVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(warningMessageVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }

    @Override
    public WarningMessageVO detail(WarningMessage warningMessage) {
        WarningMessage detail =getOne(Condition.getQueryWrapper(warningMessage));
        WarningMessageVO warningMessageVO = warningMessageWrapper.entityToVO(detail);
        return warningMessageVO;
    }

}
